package com.laoliu.example.generate.core.generate;

import com.google.common.base.CaseFormat;
import com.laoliu.example.generate.constant.CodeGeneratorConst;
import com.laoliu.example.generate.core.MyShellCallback;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Model & Mapper 代码生成器
 * Created by liuchunchun on 2019/02/14.
 */
public class ModelAndMapperGenerator extends CodeGeneratorConst {

	private static final Logger logger = LoggerFactory.getLogger(ModelAndMapperGenerator.class);
	public void genCode(String tableName) {
		String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
		Context initConfig = initConfig(tableName, modelName);
		List<String> warnings = null;
		MyBatisGenerator generator = null;
		try {
			Configuration cfg = new Configuration();
			cfg.addContext(initConfig);
			cfg.validate();
			
			MyShellCallback callback = new MyShellCallback(true);
			warnings = new ArrayList<String>();
			generator = new MyBatisGenerator(cfg, callback, warnings);
			generator.generate(null);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("Model 和  Mapper 生成失败!", e);
		}
		
		if (generator == null || generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) {
			throw new RuntimeException("Model 和  Mapper 生成失败, warnings: " + warnings);
		}
		
		logger.info(modelName, "{}.java 生成成功!");
		logger.info(modelName, "{}Mapper.java 生成成功!");
		logger.info(modelName, "{}Mapper.xml 生成成功!");
	}
	
	/**
	 * 完善初始化环境
	 * @param tableName 表名
	 * @param modelName 自定义实体类名, 为null则默认将表名下划线转成大驼峰形式
	 * @param sign 区分字段, 规定如表 gen_test_demo, 则 test 即为区分字段
	 */
	private Context initConfig(String tableName, String modelName) {
		Context context = null;
		try {
			context = initMybatisGeneratorContext();
			TableConfiguration tableConfiguration = new TableConfiguration(context);
			tableConfiguration.setCountByExampleStatementEnabled(false);
			tableConfiguration.setDeleteByExampleStatementEnabled(false);
			tableConfiguration.setSelectByExampleStatementEnabled(false);
			tableConfiguration.setUpdateByExampleStatementEnabled(false);
			IgnoredColumn ignoredColumn = new IgnoredColumn("DT_LAST_MODI");
			tableConfiguration.addIgnoredColumn(ignoredColumn);
	        tableConfiguration.setTableName(tableName);
	        tableConfiguration.setDomainObjectName(modelName);
	        tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));

	        if(JDBC_DRIVER_CLASS_NAME.equals("oracle.jdbc.driver.OracleDriver") || JDBC_DRIVER_CLASS_NAME.equals("oracle.jdbc.OracleDriver")) {
				tableConfiguration.setSchema(JDBC_USERNAME);
				tableConfiguration.addProperty(PropertyRegistry.TABLE_RUNTIME_TABLE_NAME, tableName);
				tableConfiguration.addProperty(PropertyRegistry.TABLE_IGNORE_QUALIFIERS_AT_RUNTIME, "true");
			}
	        context.addTableConfiguration(tableConfiguration);
		} catch (Exception e) {
			throw new RuntimeException("ModelAndMapperGenerator 初始化环境异常!", e);
		}
		return context;
	}

	/**
	 * Mybatis 代码自动生成基本配置
	 * @return
	 */
	public Context initMybatisGeneratorContext() {
		Context context = new Context(ModelType.FLAT);
		context.setId("MysqlContext");
		context.setTargetRuntime("MyBatis3");
		context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
		context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");
		context.addProperty("xmlMergeable", "true");
		context.addProperty("javaMergeable", "true");

		JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
		jdbcConnectionConfiguration.setConnectionURL(JDBC_URL);
		jdbcConnectionConfiguration.setUserId(JDBC_USERNAME);
		jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD);
		jdbcConnectionConfiguration.setDriverClass(JDBC_DRIVER_CLASS_NAME);
		jdbcConnectionConfiguration.addProperty("remarksReporting","true");
		context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);

		File modelFile = new File(API_PATH_JAVA+"liuchunchun.txt");
		if (!modelFile.getParentFile().exists()) {
			modelFile.getParentFile().mkdirs();
		}
		File mapperXmlFile = new File(PROJ_PATH_RESOURCE+"liuchunchun.txt");
		if (!mapperXmlFile.getParentFile().exists()) {
			mapperXmlFile.getParentFile().mkdirs();
		}

		JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
		javaModelGeneratorConfiguration.setTargetProject(API_PATH_JAVA);
		javaModelGeneratorConfiguration.setTargetPackage(MODEL_PACKAGE);
		javaModelGeneratorConfiguration.addProperty("enableSubPackages","true");
		javaModelGeneratorConfiguration.addProperty("trimStrings","true");
		context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);

		JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
		javaClientGeneratorConfiguration.setTargetProject(PROJ_PATH_JAVA);
		javaClientGeneratorConfiguration.setTargetPackage(MAPPER_PACKAGE );
		javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
		context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);

		SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
		sqlMapGeneratorConfiguration.setTargetProject(PROJ_PATH_RESOURCE);
		sqlMapGeneratorConfiguration.setTargetPackage(MAPPER_PACKAGE);
		context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);

		// 增加 mapper 插件
		/*
		 * 目前取消使用，不需要基础类
		 * */
		addMapperPlugin(context);
		/*
		 * 去掉注释
		 * */
		addMapperGender(context);

		return context;
	}

	private void addMapperGender(Context context) {
		CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration();
		commentGeneratorConfiguration.setConfigurationType("com.laoliu.example.generate.core.MyCommentGenerator");
		commentGeneratorConfiguration.addProperty("suppressAllComments","false");
		commentGeneratorConfiguration.addProperty("suppressDate","true");
		context.setCommentGeneratorConfiguration(commentGeneratorConfiguration);
	}

	/**
	 * 增加 Mapper 插件
	 * @param context
	 */
	private void addMapperPlugin(Context context) {
		PluginConfiguration equalsHashCodePlugin = new PluginConfiguration();
		equalsHashCodePlugin.setConfigurationType("org.mybatis.generator.plugins.EqualsHashCodePlugin");
		context.addPluginConfiguration(equalsHashCodePlugin);
		PluginConfiguration mapperPlugin = new PluginConfiguration();
		mapperPlugin.setConfigurationType("com.laoliu.example.generate.core.MapperPlugin");
		mapperPlugin.addProperty("targetProject",PROJ_PATH_JAVA);
		mapperPlugin.addProperty("targetPackage",MAPPER_PACKAGE);
		context.addPluginConfiguration(mapperPlugin);
		// 创建 Service 接口
		File modelFile = new File(MAPPER_PATH+"/liuchunchun.txt");
		// 查看父级目录是否存在, 不存在则创建
		if (!modelFile.getParentFile().exists()) {
			modelFile.getParentFile().mkdirs();
		}

		PluginConfiguration pluginConfiguration = new PluginConfiguration();
		pluginConfiguration.setConfigurationType("com.laoliu.example.generate.core.SerializablePlugin");
		pluginConfiguration.addProperty("suppressJavaInterface", "false");
		context.addPluginConfiguration(pluginConfiguration);

		pluginConfiguration = new PluginConfiguration();
		pluginConfiguration.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
		//pluginConfiguration.addProperty("suppressJavaInterface", "false");
		context.addPluginConfiguration(pluginConfiguration);
	}
}
